<template>
  <div class="day2">
    <!-- planA -->
    <div class="counter">
      <div class="nums">
        <!-- item  1~5 -->
        <div v-for="item in sum" :key="item" class="item"
          :class="{ in: now.val == item&&now.status=='in', out: now.val == item&&now.status=='out' }">{{ item }}
        </div>
      </div>
      <el-button type="primary" @click="startCount">开始计时</el-button>
    </div>
    <!-- planB -->
    <div class="counter">
      <div class="nums">
        <!-- TransitionGroup不支持mode 不会监听animation结束时移除/添加类名 -->
        <Transition name="count-down" mode="out-in">
          <div class="item" v-if="isShow">{{ countNum }}
          </div>
        </Transition>
      </div>
      <el-button type="primary" @click="startCount2">开始计时</el-button>
    </div>
    <!-- ***************探索动画的核心逻辑*********************** -->
    <div class="test">
      <Transition name="test" mode="out-in">
        <div class="block block1" v-if="testShow">
        </div>
        <div class="block block2" v-else>
        </div>
      </Transition>
      <div class="btn" @click="testShow=!testShow">
        <span>切换</span>
      </div>
    </div>
    <!-- ---原生通过添加/移除 动画类名 观察---------------- -->
    <div class="orign-test">
      <div class="block block1" :class="{'test-leave-active':isLeave,'test-enter-active':!isLeave,}"
        :style="`transform:scale(${isLeave?0:1})`">
      </div>
      <div class="btn" @click="isLeave=!isLeave">
        添加/移除animation
      </div>
      <div class="focus">由本例可看出 若只是添加animation 并没有在终止态结束后 把元素状态对接，就会在动画结束后 依旧显示元素的css 而不是animation 100%时的状态
        <br />
        tip:只添加消失动画
        发现动画结束后元素还存在，因为元素本身没设置scale//可将style注释掉再观察
        <br />
        通过style这儿给它对接首尾状态，实际上
        触发动画时 会忽略你对元素设置的与动画调整的同一个css 在动画结束后 你设置重复的css将起效
      </div>
    </div>
    <div class="tips">
      <div>1、注意动画的起始与终止状态要与元素调整的起始与终止对接 若能保证这一点 仅设置enter-active leave-active足矣</div>
      <div>2、倒计时动画的核心是 <span class="my-tip">判断要不要显示--起始动画0.5s--终止动画0.5s--换数字</span>
        这样循环
      </div>
      <div>3、方案1是通过对象 使一个数字具有两种状态。方案2是通过 状态标志位 控制出现与消失，期间动态修改数据</div>
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'
const sum = ref(5)
//  --------planA------------
//依赖dom监控动画结束太麻烦，给一个数字两种状态，1s拆两半，不同状态应用不同类名即可
const now = ref({ val: sum.value, status: '' })
//刚进去status不可以是out 不然会自减1后才出现展示动画
let timer = null
function startCount() {
  now.value = { val: sum.value, status: '' }//重置
  if (timer) {
    clearInterval(timer)
  }
  timer = setInterval(() => {
    if (now.value.val > 0) {
      if (now.value.status == 'in') {
        now.value.status = 'out'
      } else if (now.value.status == 'out') {
        now.value.val--
        now.value.status = 'in'
      } else {
        now.value.status = 'in'
      }
    } else {
      now.value = { val: sum.value, status: '' }
      clearInterval(timer)
    }
  }, 500)
}
// --------planB-------------
const isShow = ref(false)
const countNum = ref(null)
let timer2 = null
function startCount2() {
  //重复点击 重新赋值(由于首次赋予动画前 isShow为false 走逻辑显示时会先减一再开启展示动画，所以提前补偿1)
  countNum.value = sum.value
  if (timer2) { clearInterval(timer2) }

  timer2 = setInterval(() => {
    if (countNum.value > 0) {
      if (isShow.value) {
        isShow.value = false
        countNum.value--
      } else {
        isShow.value = true
      }
    } else {
      countNum.value = sum.value
      clearInterval(timer2)
    }
  }, 500)
}
// -------------------------------------------
const testShow = ref(true)
const isLeave = ref(false)
</script>

<style lang="scss" scoped>
.day2 {
  width: 100vw;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;

  .counter {
    display: flex;
    flex-direction: column;
    align-items: center;
    width: 100%;

    .nums {
      color: #3498db;
      font-size: 50px;
      position: relative;
      overflow: hidden;
      width: 250px;
      height: 50px;
    }

    .nums .item {
      position: absolute;
      line-height: 50px;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%) rotate(180deg);
      transform-origin: bottom center;
    }

    .nums .item.in {
      // transform: translate(-50%, -50%) rotate(0deg);
      animation: goIn 0.5s ease-in-out;
    }

    .nums .item.out {
      animation: goOut 0.5s ease-in-out;
    }

    //---------------------- planB-------------------
    .count-down-enter-active {
      animation: goIn 0.5s;
    }

    .count-down-leave-active {
      animation: goOut 0.5s;
    }

    //************************************************ */
    @keyframes goIn {
      0% {
        transform: translate(-50%, -50%) rotate(120deg);
      }

      30% {
        transform: translate(-50%, -50%) rotate(-20deg);
      }

      60% {
        transform: translate(-50%, -50%) rotate(10deg);
      }

      100% {
        transform: translate(-50%, -50%) rotate(0deg);
      }
    }

    @keyframes goOut {
      0% {
        transform: translate(-50%, -50%) rotate(0deg);
      }

      60% {
        transform: translate(-50%, -50%) rotate(20deg);
      }

      100% {
        transform: translate(-50%, -50%) rotate(-120deg);
      }
    }
  }

  // **************************************
  .test,
  .orign-test {
    margin-top: 50px;

    .block {
      width: 100px;
      height: 100px;
    }

    .block1 {
      background-color: rgb(228, 146, 146);
    }

    .block2 {
      background-color: rgb(110, 182, 241);
    }


    .test-enter-active {
      animation: show 0.2s ease-out;
    }

    .test-leave-active {
      animation: hide 0.2s ease-out;
    }

    //.v-enter-from,.v-leave-to 这俩被v-if控制 也不用写
    //.v-enter-to,.v-leave-from 这俩被动画show的100%和hide的0%承包，其实不写也行
    //写动画 核心： 起始状态--过渡--终止状态 过渡的首尾要和前后状态一致
    @keyframes show {
      0% {
        transform: scale(0);
      }

      30% {
        transform: scale(1.4);
      }

      100% {
        transform: scale(1);
      }
    }

    @keyframes hide {
      0% {
        transform: scale(1);
      }

      100% {
        transform: scale(0);
      }
    }
  }

  .orign-test {
    width: 500px;
    display: flex;
    flex-direction: column;
    align-items: center;
    margin-top: 17px;

    .focus {
      padding: 7px;
      border-radius: 4px;
      background-color: rgb(181, 209, 241);
      width: 722px;
      margin-top: 3px;
    }
  }

  .btn {
    margin-top: 10px;
    width: fit-content;
    line-height: 20px;
    padding: 7px;
    border-radius: 5px;
    background-color: rgb(148, 185, 240);
    color: #fff;
    white-space: nowrap;
    cursor: pointer;

    span {
      position: relative;
      transition: 0.3s;

      &:after {
        content: '\00bb';
        position: absolute;
        opacity: 0;
        top: 50%;
        transform: translateY(-50%);
        right: -50px;
        transition: 0.5s;
      }
    }

    &:hover span {
      padding-right: 50px;
    }

    &:hover span:after {
      opacity: 1;
      right: 0;
    }
  }
}
</style>
